<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>CAS Authentication :: Spring Security</title>
<link rel="canonical" href="../../../servlet/authentication/cas.html">
<link rel="prev" href="jaas.html">
<link rel="next" href="x509.html">
<meta name="generator" content="Antora 3.0.0">
<link rel="stylesheet" href="../../../_/css/site.css">
<link href="../../../_/img/favicon.ico" rel='shortcut icon' type='image/vnd.microsoft.icon'>
<link rel="stylesheet" href="../../../_/css/vendor/docsearch.min.css">

<script>var uiRootPath = '../../../_'</script>
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://spring.io">
<img id="springlogo" class="block" src="../../../_/img/spring-logo.svg" alt="Spring">
</a>
<button class="navbar-burger" data-target="topbar-nav">
<span></span>
<span></span>
<span></span>
</button>
</div>
<div id="topbar-nav" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="cas.html#">Why Spring</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/why-spring">Overview</a>
<a class="navbar-item" href="https://spring.io/microservices">Microservices</a>
<a class="navbar-item" href="https://spring.io/reactive">Reactive</a>
<a class="navbar-item" href="https://spring.io/event-driven">Event Driven</a>
<a class="navbar-item" href="https://spring.io/cloud">Cloud</a>
<a class="navbar-item" href="https://spring.io/web-applications">Web Applications</a>
<a class="navbar-item" href="https://spring.io/serverless">Serverless</a>
<a class="navbar-item" href="https://spring.io/batch">Batch</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="cas.html#">Learn</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/learn">Overview</a>
<a class="navbar-item" href="https://spring.io/quickstart">Quickstart</a>
<a class="navbar-item" href="https://spring.io/guides">Guides</a>
<a class="navbar-item" href="https://spring.io/blog">Blog</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="cas.html#">Projects</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/projects">Overview</a>
<a class="navbar-item" href="https://spring.io/projects/spring-boot">Spring Boot</a>
<a class="navbar-item" href="https://spring.io/projects/spring-framework">Spring Framework</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud">Spring Cloud</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud-dataflow">Spring Cloud Data Flow</a>
<a class="navbar-item" href="https://spring.io/projects/spring-data">Spring Data</a>
<a class="navbar-item" href="https://spring.io/projects/spring-integration">Spring Integration</a>
<a class="navbar-item" href="https://spring.io/projects/spring-batch">Spring Batch</a>
<a class="navbar-item" href="https://spring.io/projects/spring-security">Spring Security</a>
<a class="navbar-item navbar-item-special" href="https://spring.io/projects">View all projects</a>
<a class="navbar-item" href="https://spring.io/tools">Spring Tools 4</a>
<a class="navbar-item navbar-item-special-2" href="https://start.spring.io">Spring Initializr <svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><polyline points="15 10.94 15 15 1 15 1 1 5.06 1" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><polyline points="8.93 1 15 1 15 7.07" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><line x1="15" y1="1" x2="8" y2="8" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></line></svg></a>
</div>
</div>
<a class="navbar-item" href="https://spring.io/training">Training</a>
<a class="navbar-item" href="https://spring.io/support">Support</a>
<div class="navbar-item has-dropdown is-hoverable is-community">
<a class="navbar-link" href="cas.html#">Community</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/community">Overview</a>
<a class="navbar-item" href="https://spring.io/events">Events</a>
<a class="navbar-item" href="https://spring.io/team">Team</a>
</div>
</div>
</div>
</div>
<div id="switch-theme">
<input type="checkbox" id="switch-theme-checkbox" />
<label for="switch-theme-checkbox">Dark Theme</label>
</div>
</nav>
</header>
<div class="body">
<div class="nav-container" data-component="ROOT" data-version="5.6.1">
<aside class="nav">
<div class="panels">
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<h3 class="title"><a href="../../index.html">Spring Security</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../index.html">Overview</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../prerequisites.html">Prerequisites</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../community.html">Community</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../whats-new.html">What&#8217;s New</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../getting-spring-security.html">Getting Spring Security</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/index.html">Features</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/authentication/index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/authentication/password-storage.html">Password Storage</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/headers.html">HTTP Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/cryptography.html">Cryptography</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/data.html">Spring Data</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/concurrency.html">Java&#8217;s Concurrency APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/jackson.html">Jackson</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/localization.html">Localization</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../modules.html">Project Modules</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../samples.html">Samples</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../index.html">Servlet Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../architecture.html">Architecture</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="architecture.html">Authentication Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="passwords/index.html">Username/Password</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="passwords/input.html">Reading Username/Password</a>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/form.html">Form</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/basic.html">Basic</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/digest.html">Digest</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="passwords/storage.html">Password Storage</a>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/in-memory.html">In Memory</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/jdbc.html">JDBC</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/user-details.html">UserDetails</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/user-details-service.html">UserDetailsService</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/password-encoder.html">PasswordEncoder</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/dao-authentication-provider.html">DaoAuthenticationProvider</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="passwords/ldap.html">LDAP</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="session-management.html">Session Management</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="rememberme.html">Remember Me</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="openid.html">OpenID</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="anonymous.html">Anonymous</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="preauth.html">Pre-Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="jaas.html">JAAS</a>
</li>
<li class="nav-item is-current-page" data-depth="3">
<a class="nav-link" href="cas.html">CAS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="x509.html">X509</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="runas.html">Run-As</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="logout.html">Logout</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="events.html">Authentication Events</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../authorization/index.html">Authorization</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/architecture.html">Authorization Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/authorize-http-requests.html">Authorize HTTP Requests</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/authorize-requests.html">Authorize HTTP Requests with FilterSecurityInterceptor</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/expression-based.html">Expression-Based Access Control</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/secure-objects.html">Secure Object Implementations</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/method-security.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authorization/acls.html">Domain Object Security ACLs</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../oauth2/login/index.html">OAuth2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/login/core.html">Core Configuration</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/login/advanced.html">Advanced Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../oauth2/client/index.html">OAuth2 Client</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/client/core.html">Core Interfaces and Classes</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/client/authorization-grants.html">OAuth2 Authorization Grants</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/client/client-authentication.html">OAuth2 Client Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/client/authorized-clients.html">OAuth2 Authorized Clients</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../oauth2/resource-server/index.html">OAuth2 Resource Server</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/resource-server/jwt.html">JWT</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/resource-server/opaque-token.html">Opaque Token</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/resource-server/multitenancy.html">Multitenancy</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../oauth2/resource-server/bearer-tokens.html">Bearer Tokens</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../saml2/index.html">SAML2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../saml2/login/index.html">SAML2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../saml2/login/overview.html">SAML2 Log In Overview</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../saml2/login/authentication-requests.html">SAML2 Authentication Requests</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../saml2/login/authentication.html">SAML2 Authentication Responses</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../saml2/logout.html">SAML2 Logout</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../saml2/metadata.html">SAML2 Metadata</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/csrf.html">Cross Site Request Forgery (CSRF) for Servlet Environments</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/headers.html">Security HTTP Response Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/http.html">HTTP</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/firewall.html">HttpFirewall</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/concurrency.html">Concurrency</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/jackson.html">Jackson</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/localization.html">Localization</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/servlet-api.html">Servlet APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/data.html">Spring Data</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/mvc.html">Spring MVC</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/websocket.html">WebSocket</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/cors.html">Spring&#8217;s CORS Support</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/jsp-taglibs.html">JSP Taglib</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Configuration</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/java.html">Java Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/kotlin.html">Kotlin Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/xml-namespace.html">Namespace Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../test/index.html">Testing</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/method.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc/index.html">MockMvc Support</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc/setup.html">MockMvc Setup</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../test/mockmvc/request-post-processors.html">Security RequestPostProcessors</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/authentication.html">Mocking Users</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/csrf.html">Mocking CSRF</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/form-login.html">Mocking Form Login</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/http-basic.html">Mocking HTTP Basic</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/oauth2.html">Mocking OAuth2</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../test/mockmvc/logout.html">Mocking Logout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc/request-builders.html">Security RequestBuilders</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc/result-matchers.html">Security ResultMatchers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc/result-handlers.html">Security ResultHandlers</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../appendix/index.html">Appendix</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../appendix/database-schema.html">Database Schemas</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../appendix/namespace/index.html">XML Namespace</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../appendix/namespace/authentication-manager.html">Authentication Services</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../appendix/namespace/http.html">Web Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../appendix/namespace/method-security.html">Method Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../appendix/namespace/ldap.html">LDAP Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../appendix/namespace/websocket.html">WebSocket Security</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../appendix/faq.html">FAQ</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/index.html">Reactive Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../reactive/getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authentication</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authentication/x509.html">X.509 Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authentication/logout.html">Logout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authorization</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authorization/method.html">EnableReactiveMethodSecurity</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/oauth2/login/index.html">OAuth2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/login/core.html">Core Configuration</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/login/advanced.html">Advanced Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/oauth2/client/index.html">OAuth2 Client</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/client/core.html">Core Interfaces and Classes</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/client/authorization-grants.html">OAuth2 Authorization Grants</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/client/client-authentication.html">OAuth2 Client Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/client/authorized-clients.html">OAuth2 Authorized Clients</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/oauth2/resource-server/index.html">OAuth2 Resource Server</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/resource-server/jwt.html">JWT</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/resource-server/opaque-token.html">Opaque Token</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/resource-server/multitenancy.html">Multitenancy</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/oauth2/resource-server/bearer-tokens.html">Bearer Tokens</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/headers.html">Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Integrations</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/integrations/cors.html">CORS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/integrations/rsocket.html">RSocket</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/test/index.html">Testing</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/test/method.html">Testing Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/test/web/index.html">Testing Web Security</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/test/web/setup.html">WebTestClient Setup</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/test/web/authentication.html">Testing Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/test/web/csrf.html">Testing CSRF</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../reactive/test/web/oauth2.html">Testing OAuth 2.0</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../reactive/configuration/webflux.html">WebFlux Security</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="nav-panel-explore" data-panel="explore">
<div class="context">
<span class="title">Spring Security</span>
<span class="version">5.6.1</span>
</div>
<ul class="components">
<li class="component is-current">
<a class="title" href="../../../index.html">Spring Security</a>
<ul class="versions">
<li class="version">
<a href="../../../6.0/index.html">6.0.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../6.0.0-M3/index.html">6.0.0-M3</a>
</li>
<li class="version">
<a href="../../../6.0.0-M2/index.html">6.0.0-M2</a>
</li>
<li class="version">
<a href="../../../6.0.0-M1/index.html">6.0.0-M1</a>
</li>
<li class="version">
<a href="../../../5.7/index.html">5.7.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../5.7.0-RC1/index.html">5.7.0-RC1</a>
</li>
<li class="version">
<a href="../../../5.7.0-M3/index.html">5.7.0-M3</a>
</li>
<li class="version">
<a href="../../../5.7.0-M2/index.html">5.7.0-M2</a>
</li>
<li class="version">
<a href="../../../5.7.0-M1/index.html">5.7.0-M1</a>
</li>
<li class="version">
<a href="../../../5.6.4/index.html">5.6.4-SNAPSHOT</a>
</li>
<li class="version is-latest">
<a href="../../../index.html">5.6.3</a>
</li>
<li class="version">
<a href="../../../5.6.2/index.html">5.6.2</a>
</li>
<li class="version is-current">
<a href="../../index.html">5.6.1</a>
</li>
<li class="version">
<a href="../../../5.6.0/index.html">5.6.0</a>
</li>
<li class="version">
<a href="../../../5.6.0-RC1/index.html">5.6.0-RC1</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
</div>
<main class="article">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="../../index.html">Spring Security</a></li>
<li><a href="../index.html">Servlet Applications</a></li>
<li><a href="index.html">Authentication</a></li>
<li><a href="cas.html">CAS</a></li>
</ul>
</nav>
<div class="search">
<input id="search-input" type="text" placeholder="Search docs">
</div>
<div class="page-versions">
<button class="version-menu-toggle" title="Show other versions of page">5.6.1</button>
<div class="version-menu">
<a class="version is-missing" href="../../../6.0/index.html">6.0.0-SNAPSHOT</a>
<a class="version is-missing" href="../../../6.0.0-M3/index.html">6.0.0-M3</a>
<a class="version is-missing" href="../../../6.0.0-M2/index.html">6.0.0-M2</a>
<a class="version is-missing" href="../../../6.0.0-M1/index.html">6.0.0-M1</a>
<a class="version" href="../../../5.7/servlet/authentication/cas.html">5.7.0-SNAPSHOT</a>
<a class="version" href="../../../5.7.0-RC1/servlet/authentication/cas.html">5.7.0-RC1</a>
<a class="version" href="../../../5.7.0-M3/servlet/authentication/cas.html">5.7.0-M3</a>
<a class="version" href="../../../5.7.0-M2/servlet/authentication/cas.html">5.7.0-M2</a>
<a class="version" href="../../../5.7.0-M1/servlet/authentication/cas.html">5.7.0-M1</a>
<a class="version" href="../../../5.6.4/servlet/authentication/cas.html">5.6.4-SNAPSHOT</a>
<a class="version" href="../../../servlet/authentication/cas.html">5.6.3</a>
<a class="version" href="../../../5.6.2/servlet/authentication/cas.html">5.6.2</a>
<a class="version is-current" href="cas.html">5.6.1</a>
<a class="version" href="../../../5.6.0/servlet/authentication/cas.html">5.6.0</a>
<a class="version" href="../../../5.6.0-RC1/servlet/authentication/cas.html">5.6.0-RC1</a>
</div>
</div>
<div class="edit-this-page"><a href="https://github.com/spring-projects/spring-security/blob/5.6.1/docs/modules/ROOT/pages/servlet/authentication/cas.adoc">Edit this Page</a></div>
</div>
<div class="content">
<aside class="toc sidebar" data-title="Contents" data-levels="2">
<div class="toc-menu"></div>
</aside>
<article class="doc">
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p> For the latest stable version, please use <a href="../../../servlet/authentication/cas.html">Spring Security 5.6.3</a>!</p>
</div>
</td>
</tr></tbody>
</table>
</div>
<h1 id="page-title" class="page">CAS Authentication</h1>
<div class="sect1">
<h2 id="cas-overview"><a class="anchor" href="cas.html#cas-overview"></a>Overview</h2>
<div class="sectionbody">
<div class="paragraph">
<p>JA-SIG produces an enterprise-wide single sign on system known as CAS.
Unlike other initiatives, JA-SIG&#8217;s Central Authentication Service is open source, widely used, simple to understand, platform independent, and supports proxy capabilities.
Spring Security fully supports CAS, and provides an easy migration path from single-application deployments of Spring Security through to multiple-application deployments secured by an enterprise-wide CAS server.</p>
</div>
<div class="paragraph">
<p>You can learn more about CAS at <a href="https://www.apereo.org" class="bare">https://www.apereo.org</a>.
You will also need to visit this site to download the CAS Server files.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="cas-how-it-works"><a class="anchor" href="cas.html#cas-how-it-works"></a>How CAS Works</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Whilst the CAS web site contains documents that detail the architecture of CAS, we present the general overview again here within the context of Spring Security.
Spring Security 3.x supports CAS 3.
At the time of writing, the CAS server was at version 3.4.</p>
</div>
<div class="paragraph">
<p>Somewhere in your enterprise you will need to setup a CAS server.
The CAS server is simply a standard WAR file, so there isn&#8217;t anything difficult about setting up your server.
Inside the WAR file you will customise the login and other single sign on pages displayed to users.</p>
</div>
<div class="paragraph">
<p>When deploying a CAS 3.4 server, you will also need to specify an <code>AuthenticationHandler</code> in the <code>deployerConfigContext.xml</code> included with CAS.
The <code>AuthenticationHandler</code> has a simple method that returns a boolean as to whether a given set of Credentials is valid.
Your <code>AuthenticationHandler</code> implementation will need to link into some type of backend authentication repository, such as an LDAP server or database.
CAS itself includes numerous <code>AuthenticationHandler</code>s out of the box to assist with this.
When you download and deploy the server war file, it is set up to successfully authenticate users who enter a password matching their username, which is useful for testing.</p>
</div>
<div class="paragraph">
<p>Apart from the CAS server itself, the other key players are of course the secure web applications deployed throughout your enterprise.
These web applications are known as "services".
There are three types of services.
Those that authenticate service tickets, those that can obtain proxy tickets, and those that authenticate proxy tickets.
Authenticating a proxy ticket differs because the list of proxies must be validated and often times a proxy ticket can be reused.</p>
</div>
<div class="sect2">
<h3 id="cas-sequence"><a class="anchor" href="cas.html#cas-sequence"></a>Spring Security and CAS Interaction Sequence</h3>
<div class="paragraph">
<p>The basic interaction between a web browser, CAS server and a Spring Security-secured service is as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The web user is browsing the service&#8217;s public pages.
CAS or Spring Security is not involved.</p>
</li>
<li>
<p>The user eventually requests a page that is either secure or one of the beans it uses is secure.
Spring Security&#8217;s <code>ExceptionTranslationFilter</code> will detect the <code>AccessDeniedException</code> or <code>AuthenticationException</code>.</p>
</li>
<li>
<p>Because the user&#8217;s <code>Authentication</code> object (or lack thereof) caused an <code>AuthenticationException</code>, the <code>ExceptionTranslationFilter</code> will call the configured <code>AuthenticationEntryPoint</code>.
If using CAS, this will be the <code>CasAuthenticationEntryPoint</code> class.</p>
</li>
<li>
<p>The <code>CasAuthenticationEntryPoint</code> will redirect the user&#8217;s browser to the CAS server.
It will also indicate a <code>service</code> parameter, which is the callback URL for the Spring Security service (your application).
For example, the URL to which the browser is redirected might be <a href="https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas" class="bare">https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas</a>.</p>
</li>
<li>
<p>After the user&#8217;s browser redirects to CAS, they will be prompted for their username and password.
If the user presents a session cookie which indicates they&#8217;ve previously logged on, they will not be prompted to login again (there is an exception to this procedure, which we&#8217;ll cover later).
CAS will use the <code>PasswordHandler</code> (or <code>AuthenticationHandler</code> if using CAS 3.0) discussed above to decide whether the username and password is valid.</p>
</li>
<li>
<p>Upon successful login, CAS will redirect the user&#8217;s browser back to the original service.
It will also include a <code>ticket</code> parameter, which is an opaque string representing the "service ticket".
Continuing our earlier example, the URL the browser is redirected to might be <a href="https://server3.company.com/webapp/login/cas?ticket=ST-0-ER94xMJmn6pha35CQRoZ" class="bare">https://server3.company.com/webapp/login/cas?ticket=ST-0-ER94xMJmn6pha35CQRoZ</a>.</p>
</li>
<li>
<p>Back in the service web application, the <code>CasAuthenticationFilter</code> is always listening for requests to <code>/login/cas</code> (this is configurable, but we&#8217;ll use the defaults in this introduction).
The processing filter will construct a <code>UsernamePasswordAuthenticationToken</code> representing the service ticket.
The principal will be equal to <code>CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>, whilst the credentials will be the service ticket opaque value.
This authentication request will then be handed to the configured <code>AuthenticationManager</code>.</p>
</li>
<li>
<p>The <code>AuthenticationManager</code> implementation will be the <code>ProviderManager</code>, which is in turn configured with the <code>CasAuthenticationProvider</code>.
The <code>CasAuthenticationProvider</code> only responds to <code>UsernamePasswordAuthenticationToken</code>s containing the CAS-specific principal (such as <code>CasAuthenticationFilter.CAS_STATEFUL_IDENTIFIER</code>) and <code>CasAuthenticationToken</code>s (discussed later).</p>
</li>
<li>
<p><code>CasAuthenticationProvider</code> will validate the service ticket using a <code>TicketValidator</code> implementation.
This will typically be a <code>Cas20ServiceTicketValidator</code> which is one of the classes included in the CAS client library.
In the event the application needs to validate proxy tickets, the <code>Cas20ProxyTicketValidator</code> is used.
The <code>TicketValidator</code> makes an HTTPS request to the CAS server in order to validate the service ticket.
It may also include a proxy callback URL, which is included in this example: <a href="https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/login/cas/proxyreceptor" class="bare">https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Flogin/cas&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/login/cas/proxyreceptor</a>.</p>
</li>
<li>
<p>Back on the CAS server, the validation request will be received.
If the presented service ticket matches the service URL the ticket was issued to, CAS will provide an affirmative response in XML indicating the username.
If any proxy was involved in the authentication (discussed below), the list of proxies is also included in the XML response.</p>
</li>
<li>
<p>[OPTIONAL] If the request to the CAS validation service included the proxy callback URL (in the <code>pgtUrl</code> parameter), CAS will include a <code>pgtIou</code> string in the XML response.
This <code>pgtIou</code> represents a proxy-granting ticket IOU.
The CAS server will then create its own HTTPS connection back to the <code>pgtUrl</code>.
This is to mutually authenticate the CAS server and the claimed service URL.
The HTTPS connection will be used to send a proxy granting ticket to the original web application.
For example, <a href="https://server3.company.com/webapp/login/cas/proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH" class="bare">https://server3.company.com/webapp/login/cas/proxyreceptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</a>.</p>
</li>
<li>
<p>The <code>Cas20TicketValidator</code> will parse the XML received from the CAS server.
It will return to the <code>CasAuthenticationProvider</code> a <code>TicketResponse</code>, which includes the username (mandatory), proxy list (if any were involved), and proxy-granting ticket IOU (if the proxy callback was requested).</p>
</li>
<li>
<p>Next <code>CasAuthenticationProvider</code> will call a configured <code>CasProxyDecider</code>.
The <code>CasProxyDecider</code> indicates whether the proxy list in the <code>TicketResponse</code> is acceptable to the service.
Several implementations are provided with Spring Security: <code>RejectProxyTickets</code>, <code>AcceptAnyCasProxy</code> and <code>NamedCasProxyDecider</code>.
These names are largely self-explanatory, except <code>NamedCasProxyDecider</code> which allows a <code>List</code> of trusted proxies to be provided.</p>
</li>
<li>
<p><code>CasAuthenticationProvider</code> will next request a <code>AuthenticationUserDetailsService</code> to load the <code>GrantedAuthority</code> objects that apply to the user contained in the <code>Assertion</code>.</p>
</li>
<li>
<p>If there were no problems, <code>CasAuthenticationProvider</code> constructs a <code>CasAuthenticationToken</code> including the details contained in the <code>TicketResponse</code> and the <code>GrantedAuthority</code>s.</p>
</li>
<li>
<p>Control then returns to <code>CasAuthenticationFilter</code>, which places the created <code>CasAuthenticationToken</code> in the security context.</p>
</li>
<li>
<p>The user&#8217;s browser is redirected to the original page that caused the <code>AuthenticationException</code> (or a custom destination depending on the configuration).</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>It&#8217;s good that you&#8217;re still here!
Let&#8217;s now look at how this is configured</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="cas-client"><a class="anchor" href="cas.html#cas-client"></a>Configuration of CAS Client</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The web application side of CAS is made easy due to Spring Security.
It is assumed you already know the basics of using Spring Security, so these are not covered again below.
We&#8217;ll assume a namespace based configuration is being used and add in the CAS beans as required.
Each section builds upon the previous section.
A full CAS sample application can be found in the Spring Security <a href="../../samples.html#samples" class="xref page">Samples</a>.</p>
</div>
<div class="sect2">
<h3 id="cas-st"><a class="anchor" href="cas.html#cas-st"></a>Service Ticket Authentication</h3>
<div class="paragraph">
<p>This section describes how to setup Spring Security to authenticate Service Tickets.
Often times this is all a web application requires.
You will need to add a <code>ServiceProperties</code> bean to your application context.
This represents your CAS service:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="serviceProperties"
	class="org.springframework.security.cas.ServiceProperties"&gt;
&lt;property name="service"
	value="https://localhost:8443/cas-sample/login/cas"/&gt;
&lt;property name="sendRenew" value="false"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>service</code> must equal a URL that will be monitored by the <code>CasAuthenticationFilter</code>.
The <code>sendRenew</code> defaults to false, but should be set to true if your application is particularly sensitive.
What this parameter does is tell the CAS login service that a single sign on login is unacceptable.
Instead, the user will need to re-enter their username and password in order to gain access to the service.</p>
</div>
<div class="paragraph">
<p>The following beans should be configured to commence the CAS authentication process (assuming you&#8217;re using a namespace configuration):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;security:http entry-point-ref="casEntryPoint"&gt;
...
&lt;security:custom-filter position="CAS_FILTER" ref="casFilter" /&gt;
&lt;/security:http&gt;

&lt;bean id="casFilter"
	class="org.springframework.security.cas.web.CasAuthenticationFilter"&gt;
&lt;property name="authenticationManager" ref="authenticationManager"/&gt;
&lt;/bean&gt;

&lt;bean id="casEntryPoint"
	class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"&gt;
&lt;property name="loginUrl" value="https://localhost:9443/cas/login"/&gt;
&lt;property name="serviceProperties" ref="serviceProperties"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>For CAS to operate, the <code>ExceptionTranslationFilter</code> must have its <code>authenticationEntryPoint</code> property set to the <code>CasAuthenticationEntryPoint</code> bean.
This can easily be done using <a href="../appendix/namespace/http.html#nsa-http-entry-point-ref" class="xref page">entry-point-ref</a> as is done in the example above.
The <code>CasAuthenticationEntryPoint</code> must refer to the <code>ServiceProperties</code> bean (discussed above), which provides the URL to the enterprise&#8217;s CAS login server.
This is where the user&#8217;s browser will be redirected.</p>
</div>
<div class="paragraph">
<p>The <code>CasAuthenticationFilter</code> has very similar properties to the <code>UsernamePasswordAuthenticationFilter</code> (used for form-based logins).
You can use these properties to customize things like behavior for authentication success and failure.</p>
</div>
<div class="paragraph">
<p>Next you need to add a <code>CasAuthenticationProvider</code> and its collaborators:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;security:authentication-manager alias="authenticationManager"&gt;
&lt;security:authentication-provider ref="casAuthenticationProvider" /&gt;
&lt;/security:authentication-manager&gt;

&lt;bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider"&gt;
&lt;property name="authenticationUserDetailsService"&gt;
	&lt;bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"&gt;
	&lt;constructor-arg ref="userService" /&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="serviceProperties" ref="serviceProperties" /&gt;
&lt;property name="ticketValidator"&gt;
	&lt;bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"&gt;
	&lt;constructor-arg index="0" value="https://localhost:9443/cas" /&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="key" value="an_id_for_this_auth_provider_only"/&gt;
&lt;/bean&gt;

&lt;security:user-service id="userService"&gt;
&lt;!-- Password is prefixed with {noop} to indicate to DelegatingPasswordEncoder that
NoOpPasswordEncoder should be used.
This is not safe for production, but makes reading
in samples easier.
Normally passwords should be hashed using BCrypt --&gt;
&lt;security:user name="joe" password="{noop}joe" authorities="ROLE_USER" /&gt;
...
&lt;/security:user-service&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>CasAuthenticationProvider</code> uses a <code>UserDetailsService</code> instance to load the authorities for a user, once they have been authenticated by CAS.
We&#8217;ve shown a simple in-memory setup here.
Note that the <code>CasAuthenticationProvider</code> does not actually use the password for authentication, but it does use the authorities.</p>
</div>
<div class="paragraph">
<p>The beans are all reasonably self-explanatory if you refer back to the <a href="cas.html#cas-how-it-works">How CAS Works</a> section.</p>
</div>
<div class="paragraph">
<p>This completes the most basic configuration for CAS.
If you haven&#8217;t made any mistakes, your web application should happily work within the framework of CAS single sign on.
No other parts of Spring Security need to be concerned about the fact CAS handled authentication.
In the following sections we will discuss some (optional) more advanced configurations.</p>
</div>
</div>
<div class="sect2">
<h3 id="cas-singlelogout"><a class="anchor" href="cas.html#cas-singlelogout"></a>Single Logout</h3>
<div class="paragraph">
<p>The CAS protocol supports Single Logout and can be easily added to your Spring Security configuration.
Below are updates to the Spring Security configuration that handle Single Logout</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;security:http entry-point-ref="casEntryPoint"&gt;
...
&lt;security:logout logout-success-url="/cas-logout.jsp"/&gt;
&lt;security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/&gt;
&lt;security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/&gt;
&lt;/security:http&gt;

&lt;!-- This filter handles a Single Logout Request from the CAS Server --&gt;
&lt;bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/&gt;

&lt;!-- This filter redirects to the CAS Server to signal Single Logout should be performed --&gt;
&lt;bean id="requestSingleLogoutFilter"
	class="org.springframework.security.web.authentication.logout.LogoutFilter"&gt;
&lt;constructor-arg value="https://localhost:9443/cas/logout"/&gt;
&lt;constructor-arg&gt;
	&lt;bean class=
		"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/&gt;
&lt;/constructor-arg&gt;
&lt;property name="filterProcessesUrl" value="/logout/cas"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>logout</code> element logs the user out of the local application, but does not end the session with the CAS server or any other applications that have been logged into.
The <code>requestSingleLogoutFilter</code> filter will allow the URL of <code>/spring_security_cas_logout</code> to be requested to redirect the application to the configured CAS Server logout URL.
Then the CAS Server will send a Single Logout request to all the services that were signed into.
The <code>singleLogoutFilter</code> handles the Single Logout request by looking up the <code>HttpSession</code> in a static <code>Map</code> and then invalidating it.</p>
</div>
<div class="paragraph">
<p>It might be confusing why both the <code>logout</code> element and the <code>singleLogoutFilter</code> are needed.
It is considered best practice to logout locally first since the <code>SingleSignOutFilter</code> just stores the <code>HttpSession</code> in a static <code>Map</code> in order to call invalidate on it.
With the configuration above, the flow of logout would be:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The user requests <code>/logout</code> which would log the user out of the local application and send the user to the logout success page.</p>
</li>
<li>
<p>The logout success page, <code>/cas-logout.jsp</code>, should instruct the user to click a link pointing to <code>/logout/cas</code> in order to logout out of all applications.</p>
</li>
<li>
<p>When the user clicks the link, the user is redirected to the CAS single logout URL (<a href="https://localhost:9443/cas/logout" class="bare">https://localhost:9443/cas/logout</a>).</p>
</li>
<li>
<p>On the CAS Server side, the CAS single logout URL then submits single logout requests to all the CAS Services.
On the CAS Service side, JASIG&#8217;s <code>SingleSignOutFilter</code> processes the logout request by invalidating the original session.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The next step is to add the following to your web.xml</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;filter&gt;
&lt;filter-name&gt;characterEncodingFilter&lt;/filter-name&gt;
&lt;filter-class&gt;
	org.springframework.web.filter.CharacterEncodingFilter
&lt;/filter-class&gt;
&lt;init-param&gt;
	&lt;param-name&gt;encoding&lt;/param-name&gt;
	&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;characterEncodingFilter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
&lt;listener&gt;
&lt;listener-class&gt;
	org.jasig.cas.client.session.SingleSignOutHttpSessionListener
&lt;/listener-class&gt;
&lt;/listener&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>When using the SingleSignOutFilter you might encounter some encoding issues.
Therefore it is recommended to add the <code>CharacterEncodingFilter</code> to ensure that the character encoding is correct when using the <code>SingleSignOutFilter</code>.
Again, refer to JASIG&#8217;s documentation for details.
The <code>SingleSignOutHttpSessionListener</code> ensures that when an <code>HttpSession</code> expires, the mapping used for single logout is removed.</p>
</div>
</div>
<div class="sect2">
<h3 id="cas-pt-client"><a class="anchor" href="cas.html#cas-pt-client"></a>Authenticating to a Stateless Service with CAS</h3>
<div class="paragraph">
<p>This section describes how to authenticate to a service using CAS.
In other words, this section discusses how to setup a client that uses a service that authenticates with CAS.
The next section describes how to setup a stateless service to Authenticate using CAS.</p>
</div>
<div class="sect3">
<h4 id="cas-pt-client-config"><a class="anchor" href="cas.html#cas-pt-client-config"></a>Configuring CAS to Obtain Proxy Granting Tickets</h4>
<div class="paragraph">
<p>In order to authenticate to a stateless service, the application needs to obtain a proxy granting ticket (PGT).
This section describes how to configure Spring Security to obtain a PGT building upon thencas-st[Service Ticket Authentication] configuration.</p>
</div>
<div class="paragraph">
<p>The first step is to include a <code>ProxyGrantingTicketStorage</code> in your Spring Security configuration.
This is used to store PGT&#8217;s that are obtained by the <code>CasAuthenticationFilter</code> so that they can be used to obtain proxy tickets.
An example configuration is shown below</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;!--
NOTE: In a real application you should not use an in memory implementation.
You will also want to ensure to clean up expired tickets by calling
ProxyGrantingTicketStorage.cleanup()
--&gt;
&lt;bean id="pgtStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl"/&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The next step is to update the <code>CasAuthenticationProvider</code> to be able to obtain proxy tickets.
To do this replace the <code>Cas20ServiceTicketValidator</code> with a <code>Cas20ProxyTicketValidator</code>.
The <code>proxyCallbackUrl</code> should be set to a URL that the application will receive PGT&#8217;s at.
Last, the configuration should also reference the <code>ProxyGrantingTicketStorage</code> so it can use a PGT to obtain proxy tickets.
You can find an example of the configuration changes that should be made below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider"&gt;
...
&lt;property name="ticketValidator"&gt;
	&lt;bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"&gt;
	&lt;constructor-arg value="https://localhost:9443/cas"/&gt;
		&lt;property name="proxyCallbackUrl"
		value="https://localhost:8443/cas-sample/login/cas/proxyreceptor"/&gt;
	&lt;property name="proxyGrantingTicketStorage" ref="pgtStorage"/&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The last step is to update the <code>CasAuthenticationFilter</code> to accept PGT and to store them in the <code>ProxyGrantingTicketStorage</code>.
It is important the <code>proxyReceptorUrl</code> matches the <code>proxyCallbackUrl</code> of the <code>Cas20ProxyTicketValidator</code>.
An example configuration is shown below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="casFilter"
		class="org.springframework.security.cas.web.CasAuthenticationFilter"&gt;
	...
	&lt;property name="proxyGrantingTicketStorage" ref="pgtStorage"/&gt;
	&lt;property name="proxyReceptorUrl" value="/login/cas/proxyreceptor"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="cas-pt-client-sample"><a class="anchor" href="cas.html#cas-pt-client-sample"></a>Calling a Stateless Service Using a Proxy Ticket</h4>
<div class="paragraph">
<p>Now that Spring Security obtains PGTs, you can use them to create proxy tickets which can be used to authenticate to a stateless service.
The CAS <a href="../../samples.html#samples" class="xref page">sample application</a> contains a working example in the <code>ProxyTicketSampleServlet</code>.
Example code can be found below:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">protected void doGet(HttpServletRequest request, HttpServletResponse response)
	throws ServletException, IOException {
// NOTE: The CasAuthenticationToken can also be obtained using
// SecurityContextHolder.getContext().getAuthentication()
final CasAuthenticationToken token = (CasAuthenticationToken) request.getUserPrincipal();
// proxyTicket could be reused to make calls to the CAS service even if the
// target url differs
final String proxyTicket = token.getAssertion().getPrincipal().getProxyTicketFor(targetUrl);

// Make a remote call using the proxy ticket
final String serviceUrl = targetUrl+"?ticket="+URLEncoder.encode(proxyTicket, "UTF-8");
String proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8");
...
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">protected fun doGet(request: HttpServletRequest, response: HttpServletResponse?) {
    // NOTE: The CasAuthenticationToken can also be obtained using
    // SecurityContextHolder.getContext().getAuthentication()
    val token = request.userPrincipal as CasAuthenticationToken
    // proxyTicket could be reused to make calls to the CAS service even if the
    // target url differs
    val proxyTicket = token.assertion.principal.getProxyTicketFor(targetUrl)

    // Make a remote call using the proxy ticket
    val serviceUrl: String = targetUrl + "?ticket=" + URLEncoder.encode(proxyTicket, "UTF-8")
    val proxyResponse = CommonUtils.getResponseFromServer(serviceUrl, "UTF-8")
}</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="cas-pt"><a class="anchor" href="cas.html#cas-pt"></a>Proxy Ticket Authentication</h3>
<div class="paragraph">
<p>The <code>CasAuthenticationProvider</code> distinguishes between stateful and stateless clients.
A stateful client is considered any that submits to the <code>filterProcessUrl</code> of the <code>CasAuthenticationFilter</code>.
A stateless client is any that presents an authentication request to <code>CasAuthenticationFilter</code> on a URL other than the <code>filterProcessUrl</code>.</p>
</div>
<div class="paragraph">
<p>Because remoting protocols have no way of presenting themselves within the context of an <code>HttpSession</code>, it isn&#8217;t possible to rely on the default practice of storing the security context in the session between requests.
Furthermore, because the CAS server invalidates a ticket after it has been validated by the <code>TicketValidator</code>, presenting the same proxy ticket on subsequent requests will not work.</p>
</div>
<div class="paragraph">
<p>One obvious option is to not use CAS at all for remoting protocol clients.
However, this would eliminate many of the desirable features of CAS.
As a middle-ground, the <code>CasAuthenticationProvider</code> uses a <code>StatelessTicketCache</code>.
This is used solely for stateless clients which use a principal equal to <code>CasAuthenticationFilter.CAS_STATELESS_IDENTIFIER</code>.
What happens is the <code>CasAuthenticationProvider</code> will store the resulting <code>CasAuthenticationToken</code> in the <code>StatelessTicketCache</code>, keyed on the proxy ticket.
Accordingly, remoting protocol clients can present the same proxy ticket and the <code>CasAuthenticationProvider</code> will not need to contact the CAS server for validation (aside from the first request).
Once authenticated, the proxy ticket could be used for URLs other than the original target service.</p>
</div>
<div class="paragraph">
<p>This section builds upon the previous sections to accommodate proxy ticket authentication.
The first step is to specify to authenticate all artifacts as shown below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="serviceProperties"
	class="org.springframework.security.cas.ServiceProperties"&gt;
...
&lt;property name="authenticateAllArtifacts" value="true"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The next step is to specify <code>serviceProperties</code> and the <code>authenticationDetailsSource</code> for the <code>CasAuthenticationFilter</code>.
The <code>serviceProperties</code> property instructs the <code>CasAuthenticationFilter</code> to attempt to authenticate all artifacts instead of only ones present on the <code>filterProcessUrl</code>.
The <code>ServiceAuthenticationDetailsSource</code> creates a <code>ServiceAuthenticationDetails</code> that ensures the current URL, based upon the <code>HttpServletRequest</code>, is used as the service URL when validating the ticket.
The method for generating the service URL can be customized by injecting a custom <code>AuthenticationDetailsSource</code> that returns a custom <code>ServiceAuthenticationDetails</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="casFilter"
	class="org.springframework.security.cas.web.CasAuthenticationFilter"&gt;
...
&lt;property name="serviceProperties" ref="serviceProperties"/&gt;
&lt;property name="authenticationDetailsSource"&gt;
	&lt;bean class=
	"org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource"&gt;
	&lt;constructor-arg ref="serviceProperties"/&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>You will also need to update the <code>CasAuthenticationProvider</code> to handle proxy tickets.
To do this replace the <code>Cas20ServiceTicketValidator</code> with a <code>Cas20ProxyTicketValidator</code>.
You will need to configure the <code>statelessTicketCache</code> and which proxies you want to accept.
You can find an example of the updates required to accept all proxies below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;bean id="casAuthenticationProvider"
	class="org.springframework.security.cas.authentication.CasAuthenticationProvider"&gt;
...
&lt;property name="ticketValidator"&gt;
	&lt;bean class="org.jasig.cas.client.validation.Cas20ProxyTicketValidator"&gt;
	&lt;constructor-arg value="https://localhost:9443/cas"/&gt;
	&lt;property name="acceptAnyProxy" value="true"/&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="statelessTicketCache"&gt;
	&lt;bean class="org.springframework.security.cas.authentication.EhCacheBasedTicketCache"&gt;
	&lt;property name="cache"&gt;
		&lt;bean class="net.sf.ehcache.Cache"
			init-method="initialise" destroy-method="dispose"&gt;
		&lt;constructor-arg value="casTickets"/&gt;
		&lt;constructor-arg value="50"/&gt;
		&lt;constructor-arg value="true"/&gt;
		&lt;constructor-arg value="false"/&gt;
		&lt;constructor-arg value="3600"/&gt;
		&lt;constructor-arg value="900"/&gt;
		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;/bean&gt;
&lt;/property&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
</div>
</div>
</div>
<nav class="pagination">
<span class="prev"><a href="jaas.html">JAAS</a></span>
<span class="next"><a href="x509.html">X509</a></span>
</nav>
</article>
</div>
</main>
</div>
<footer class="footer flex">
<div id="spring-links flex">
<img id="springlogo" src="../../../_/img/spring-logo.svg" alt="Spring">
<p class="smallest antialiased">© <script>var d = new Date();
        document.write(d.getFullYear());</script> <a href="https://www.vmware.com/">VMware</a>, Inc. or its affiliates. <a href="https://www.vmware.com/help/legal.html">Terms of Use</a> • <a href="https://www.vmware.com/help/privacy.html" rel="noopener noreferrer">Privacy</a> • <a href="https://spring.io/trademarks">Trademark Guidelines</a> <span id="thank-you-mobile">• <a href="https://spring.io/thank-you">Thank you</a></span> • <a href="https://www.vmware.com/help/privacy/california-privacy-rights.html">Your California Privacy Rights</a> • <a class="ot-sdk-show-settings">Cookie Settings</a> <span id="teconsent"></span></p>
<p class="smallest antialiased">Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra&trade;, and Apache Geode&trade; are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java&trade;, Java&trade; SE, Java&trade; EE, and OpenJDK&trade; are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.</p>
</div>
<div id="social-icons" class="flex jc-between">
<a href="https://www.youtube.com/user/SpringSourceDev" title="Youtube"><svg id="youtube-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle class="cls-1" cx="20" cy="20" r="20" /><path class="cls-2" d="M30.91,14.53a2.89,2.89,0,0,0-2-2C27.12,12,20,12,20,12s-7.12,0-8.9.47a2.9,2.9,0,0,0-2,2A30.56,30.56,0,0,0,8.63,20a30.44,30.44,0,0,0,.46,5.47,2.89,2.89,0,0,0,2,2C12.9,28,20,28,20,28s7.12,0,8.9-.47a2.87,2.87,0,0,0,2-2A30.56,30.56,0,0,0,31.37,20,28.88,28.88,0,0,0,30.91,14.53ZM17.73,23.41V16.59L23.65,20Z" /></svg></a>
<a href="https://github.com/spring-projects" title="Github"><svg id="github-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><path class="cls-1" d="M38,0a38,38,0,1,0,38,38A38,38,0,0,0,38,0Z" /></g><path class="cls-2" d="M38,15.59A22.95,22.95,0,0,0,30.71,60.3c1.15.21,1.57-.5,1.57-1.11s0-2,0-3.9c-6.38,1.39-7.73-3.07-7.73-3.07A6.09,6.09,0,0,0,22,48.86c-2.09-1.42.15-1.39.15-1.39a4.81,4.81,0,0,1,3.52,2.36c2,3.5,5.37,2.49,6.67,1.91a4.87,4.87,0,0,1,1.46-3.07c-5.09-.58-10.45-2.55-10.45-11.34a8.84,8.84,0,0,1,2.36-6.15,8.29,8.29,0,0,1,.23-6.07s1.92-.62,6.3,2.35a21.82,21.82,0,0,1,11.49,0c4.38-3,6.3-2.35,6.3-2.35a8.29,8.29,0,0,1,.23,6.07,8.84,8.84,0,0,1,2.36,6.15c0,8.81-5.37,10.75-10.48,11.32a5.46,5.46,0,0,1,1.56,4.25c0,3.07,0,5.54,0,6.29s.42,1.33,1.58,1.1A22.94,22.94,0,0,0,38,15.59Z" /></svg></a>
<a href="https://twitter.com/springcentral" title="Twitter"><svg id="twitter-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><circle class="cls-1" cx="37.97" cy="37.97" r="37.97" /><path id="Twitter-2" data-name="Twitter" class="cls-2" d="M55.2,22.73a15.43,15.43,0,0,1-4.88,1.91,7.56,7.56,0,0,0-5.61-2.49A7.78,7.78,0,0,0,37,30a7.56,7.56,0,0,0,.2,1.79,21.63,21.63,0,0,1-15.84-8.23,8,8,0,0,0,2.37,10.52,7.66,7.66,0,0,1-3.48-1v.09A7.84,7.84,0,0,0,26.45,41a7.54,7.54,0,0,1-2,.28A7.64,7.64,0,0,1,23,41.09a7.71,7.71,0,0,0,7.18,5.47,15.21,15.21,0,0,1-9.55,3.37,15.78,15.78,0,0,1-1.83-.11,21.41,21.41,0,0,0,11.78,3.54c14.13,0,21.86-12,21.86-22.42,0-.34,0-.68,0-1a15.67,15.67,0,0,0,3.83-4.08,14.9,14.9,0,0,1-4.41,1.24A7.8,7.8,0,0,0,55.2,22.73Z" /></svg></a>
</div>
</footer>
<script src="../../../_/js/site.js"></script>
<script async src="../../../_/js/vendor/highlight.js"></script>
<script async src="../../../_/js/vendor/tabs.js"></script>
<script src="../../../_/js/vendor/switchtheme.js"></script>
<script src="../../../_/js/vendor/docsearch.min.js"></script>

<script>
var search = docsearch({
  appId: '244V8V9FGG',
  apiKey: '82c7ead946afbac3cf98c32446154691',
  indexName: 'security-docs',
  inputSelector: '#search-input',
  autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
  algoliaOptions: { hitsPerPage: 10 }
}).autocomplete
search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
</script>
<script>if (window.parent == window) {(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', 'UA-2728886-23', 'auto', {'siteSpeedSampleRate': 100});ga('send', 'pageview');}</script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"702d40b66e7297ee","token":"bffcb8a918ae4755926f76178bfbd26b","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>
